package ru.elifantiev.cityrouter.infrastructure.adapters;

import android.os.AsyncTask;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.concurrent.atomic.AtomicBoolean;

abstract public class InfiniteAdapter extends AdapterWrapper {

    private AtomicBoolean keepLoading = new AtomicBoolean(true);
    private View loadingView = null;

    abstract protected boolean loadItems();
    abstract protected View getLoadingPlaceholder(ViewGroup parent);
    abstract protected void appendLoadedItems();

    public InfiniteAdapter(BaseAdapter wrappedOne) {
        super(wrappedOne);
    }

    public int getCount() {
        return super.getCount() + (keepLoading.get() ? 1 : 0);
    }

    public View getView(int i, View view, ViewGroup viewGroup) {
        if(i == super.getCount()) {
            if(loadingView == null) {
                loadingView = getLoadingPlaceholder(viewGroup);
                new LoadingTask().execute();
            }
            return loadingView;
        }
        else
            return super.getView(i, view, viewGroup);
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if(position == super.getCount())
            return IGNORE_ITEM_VIEW_TYPE;
        return
            super.getItemViewType(position);
    }

    protected void preExecute() {
        // ignore by default
    }

    class LoadingTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            preExecute();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            keepLoading.set(loadItems());
            return null;
        }

        @Override
        protected void onPostExecute(Void ignore) {
            appendLoadedItems();
            loadingView = null;
            notifyDataSetChanged();
        }
    }
}
